/***************************************************************************
 创建者: 华磊
 开始时间: 2019.9.20
 copyright: (C) 华友高科
 ***************************************************************************/
#include "mapfileparse.h"
#include "onemap.h"
#include <QDebug>
#include <jsoncpp/json/json.h>
#include <QFile>
#include "base64.h"
#include "mappoint.h"
#include "mappath.h"
#include <QImage>

#define D_MAP_FILE_PATH_PARSE "/agvwork/AgvFundation/fundation/data/robotData1/map/"

MapFileParse::MapFileParse()
{

}

int MapFileParse::saveMapToFile(OneMap *onemap, QString filePathIn)
{
        qDebug()<<"MapFileParse::saveMapToFile"<<filePathIn;
        std::string tmpMapInfo;
        transMapToString(onemap,tmpMapInfo);
        return writeFleetMap(filePathIn.toStdString(),tmpMapInfo);

}

int MapFileParse::loadMapFromFile(bool isLoadPicture,QString filePathIn, OneMap *onemapOut)
{
    qDebug()<<"MapFileParse::loadMapFromFile"<<filePathIn;

    std::string tmpMapInfo;
    if(1==getFleetMap(filePathIn.toStdString(),tmpMapInfo))
    {
        return transStringToMap(isLoadPicture,tmpMapInfo,onemapOut);
    }

    return -1;
}

int MapFileParse::getFleetMap(std::string mapPathIn, std::string &mapInfoReturn)
{
    QString filePathIn=QString::fromStdString(mapPathIn);
    qDebug()<<"MapFileParse::getFleetMap"<<filePathIn;

    Json::Value response;
    QFile file(filePathIn);
    if(file.exists())
    {
        if(file.open(QIODevice::ReadOnly))
        {

            QByteArray receiveByteArry = file.read(file.bytesAvailable());
            Json::Reader reader;

             Json::Value json_object;

             const char* json_document=receiveByteArry.data();
             if (!reader.parse(json_document, response))
             {

                 qDebug()<<filePathIn<<"failed load map file,json 格式错误";
                 return -2;
             }

        }
        else
        {
            qDebug()<<filePathIn<<"failed load map file,file open failed";
            return -2;
        }
    }
    else
    {
        qDebug()<<filePathIn<<"failed load map file,file not exist";
        return -1;
    }

    mapInfoReturn=response.toStyledString();
    return 1;

}

int MapFileParse::writeFleetMap(std::string mapPathIn,const  std::string &mapInfoIn)
{
    QString filePathIn=QString::fromStdString(mapPathIn);
    qDebug()<<"MapFileParse::writeFleetMap"<<filePathIn;

    QFile file(filePathIn);
    if(!file.open(QIODevice::WriteOnly| QIODevice::Text))
    {
        //消息预留
        //保存R寄存器数据到文件失败
        qDebug()<<"failed, save to map";
        return -1;
    }
    else
    {

        QString tmpString=QString::fromStdString(mapInfoIn);

        //写入内容,这里需要转码，否则报错。
    //    QByteArray str = tmpString.toUtf8();
         QByteArray str = tmpString.toLatin1();
        //写入QByteArray格式字符串
        file.write(str);

        file.close();
        file.flush();//必须加，如果不加，可能关机的时候丢失文件内容。
    }
    return 1;
}

int MapFileParse::transStringToMap(bool isLoadPicture, const std::string &mapInfoIn, OneMap *onemapOut)
{
    Json::Value response;

    QByteArray receiveByteArry = QString::fromStdString(mapInfoIn).toLatin1();
//    qDebug()<<receiveByteArry;
    Json::Reader reader;

     const char* json_document=receiveByteArry.data();

     if (!reader.parse(json_document, response))
     {
         qDebug()<<"error,,,transStringToMap";
         return -1;
     }



    onemapOut->clear();
    //地图信息
    for (int i = 0; i < response["points"].size(); ++i)
    {
        Json::Value station = response["points"][i];
        int id = station["id"].asInt();
        std::string name = station["name"].asString();
        int station_type = station["type"].asInt();
        double x = station["x"].asDouble();
        double y = station["y"].asDouble();
        double realX = station["realX"].asDouble();
        double realY = station["realY"].asDouble();
        double realA = station["realA"].asDouble();
        int labelXoffset = station["labelXoffset"].asInt();
        int labelYoffset = station["labelYoffset"].asInt();
        bool mapchange = station["mapchange"].asBool();
        bool locked = station["locked"].asBool();
        std::string ip = station["ip"].asString();
        int port = station["port"].asInt();
        int agvType = station["agvType"].asInt();
        std::string lineId = station["lineId"].asString();
        std::string actionCommand = station["actionCommand"].asString();
        int poseType = station["poseType"].asInt();

        MapPoint::Map_Point_Type t = static_cast<MapPoint::Map_Point_Type>(station_type);
        MapPoint *p = new MapPoint(id,name,t,x,y,realX,realY,realA,labelXoffset,labelYoffset,mapchange,locked,ip,port,agvType,lineId);
        p->setActionCommand(actionCommand);
        p->setPoseType((E_POSITION_TYPE)poseType);
        onemapOut->addSpirit(p);
    }

    //2.解析线路
    for (int i = 0; i < response["paths"].size(); ++i)
    {
        Json::Value line = response["paths"][i];
        int id = line["id"].asInt();
        std::string name = line["name"].asString();
        int type = line["type"].asInt();
        int start = line["start"].asInt();
        int end = line["end"].asInt();

        double p1x = line["p1x"].asDouble();
        double p1y = line["p1y"].asDouble();
        double p2x = line["p2x"].asDouble();
        double p2y = line["p2y"].asDouble();

        double p1x_real = line["p1x_real"].asDouble();
        double p1y_real = line["p1y_real"].asDouble();
        double p2x_real = line["p2x_real"].asDouble();
        double p2y_real = line["p2y_real"].asDouble();

        double length = line["length"].asDouble();
        bool locked = line["locked"].asBool();
        double speed = line["speed"].asDouble();
        int barrierType = line["barrierType"].asInt();
        int isBackMove = line["isBackMove"].asInt();

        MapPath::Map_Path_Type t = static_cast<MapPath::Map_Path_Type>(type);
        MapPath *p = new MapPath(id,name,start,end,t,length,p1x,p1y,p2x,p2y,locked,speed,p1x_real,p1y_real,p2x_real,p2y_real);
        p->setBarrierType((E_PATH_BARRIER_TYPE)barrierType);
        p->setIsBackMove(isBackMove);
        onemapOut->addSpirit(p);
    }

    //4.解析背景图片
    for (int i = 0; i < response["bkgs"].size(); ++i)
    {
        Json::Value bkg = response["bkgs"][i];
        int id = bkg["id"].asInt();
        std::string name = bkg["name"].asString();
        char *data=NULL;
        int lenlen=0;
        int width=0;
        int height=0;
        double x = bkg["x"].asDouble();
        double y = bkg["y"].asDouble();
        std::string filename = bkg["filename"].asString();
        //data
        QByteArray ba;
        if(isLoadPicture)
        {
            QString filePath=D_MAP_FILE_PATH_PARSE;
            filePath+=QString::fromStdString(filename);
            QFile *file = new QFile(filePath);
            file->open(QIODevice::ReadOnly);
            ba = file->readAll();
            file->close();

            //img
            QImage img;
            img.load(filePath);

            data=ba.data();
            lenlen=ba.length();
            width=img.width();
            height=img.height();


        }
        else
        {

        }
        MapBackground *p = new MapBackground(id,name,data, lenlen,width,height,filename);
        p->setX(x);
        p->setY(y);
        onemapOut->addSpirit(p);

    }

    //3.解析楼层
    for (int i = 0; i < response["floors"].size(); ++i)
    {
        Json::Value floor = response["floors"][i];
        int id = floor["id"].asInt();
        std::string name = floor["name"].asString();
        Json::Value points = floor["points"];
        Json::Value paths = floor["paths"];
        int bkg = floor["bkg"].asInt();
        int originX = floor["originX"].asInt();
        int originY = floor["originY"].asInt();
        double rate = floor["rate"].asDouble();
        MapFloor *p = new MapFloor(id, name);
        p->setBkg(bkg);
        p->setOriginX(originX);
        p->setOriginY(originY);
        p->setRate(rate);
        for (int k = 0; k < points.size(); ++k) {
            Json::Value point = points[k];
            p->addPoint(point.asInt());
        }
        for (int k = 0; k < paths.size(); ++k) {
            Json::Value path = paths[k];
            p->addPath(path.asInt());
        }
        onemapOut->addSpirit(p);
    }

    //5.解析block
    for (int i = 0; i < response["blocks"].size(); ++i)
    {
        Json::Value block = response["blocks"][i];
        int id = block["id"].asInt();
        std::string name = block["name"].asString();
        Json::Value spirits = block["spirits"];
        MapBlock *p = new MapBlock(id,name);
        for(int k=0;k<spirits.size();++k){
            Json::Value spirit = spirits[k];
            p->addSpirit(spirit.asInt());
        }
        onemapOut->addSpirit(p);
    }

    //6.解析group
    for (int i = 0; i < response["groups"].size(); ++i)
    {
        Json::Value group = response["groups"][i];
        int id = group["id"].asInt();
        int groupType = group["type"].asInt();
        std::string name = group["name"].asString();
        Json::Value spirits = group["spirits"];
        MapGroup *p = new MapGroup(id,name,groupType);
        for(int k=0;k<spirits.size();++k){
            Json::Value spirit = spirits[k];
            p->addSpirit(spirit.asInt());
        }
        onemapOut->addSpirit(p);
    }

    int max_id = response["maxId"].asInt();
    onemapOut->setMaxId(max_id);
    int version= response["version"].asInt();
    onemapOut->setVersion(version);
    double displayRatio=response["displayRatio"].asDouble();
    onemapOut->setDisplayRatio(displayRatio);
    return 1;
}

int MapFileParse::transMapToString(OneMap *onemap, std::string &mapInfoOut)
{


    //上传地图信息
    Json::Value request;
//    iniRequsttMsg(request);
//    request["todo"] = MSG_TODO_MAP_SET_MAP;

    std::list<MapSpirit *> allspirit = onemap->getAllElement();

    Json::Value v_points;
    Json::Value v_paths;
    Json::Value v_floors;
    Json::Value v_bkgs;
    Json::Value v_blocks;
    Json::Value v_groups;
    for (auto spirit : allspirit)
    {
        if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Point) {
            MapPoint *p = static_cast<MapPoint *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();
            pv["type"] = p->getPointType();
            pv["x"] = p->getX();
            pv["y"] = p->getY();
            pv["realX"] = p->getRealX();
            pv["realY"] = p->getRealY();
            pv["realA"] = p->getRealA();
            pv["labelXoffset"] = p->getLabelXoffset();
            pv["labelYoffset"] = p->getLabelYoffset();
            pv["mapchange"] = p->getMapChange();
            pv["locked"] = p->getLocked();
            pv["ip"] = p->getIp();
            pv["port"] = p->getPort();
            pv["agvType"] = p->getAgvType();
            pv["lineId"] = p->getLineId();
            pv["poseType"] = p->getPoseType();
            pv["actionCommand"] = p->getActionCommand();
            v_points.append(pv);
        }
        else if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Path) {
            MapPath *p = static_cast<MapPath *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();
            pv["type"] = p->getPathType();
            pv["start"] = p->getStart();
            pv["end"] = p->getEnd();
            pv["p1x"] = p->getP1x();
            pv["p1y"] = p->getP1y();
            pv["p2x"] = p->getP2x();
            pv["p2y"] = p->getP2y();

            pv["p1x_real"] = p->getP1x_real();
            pv["p1y_real"] = p->getP1y_real();
            pv["p2x_real"] = p->getP2x_real();
            pv["p2y_real"] = p->getP2y_real();


            pv["speed"] = p->getSpeed();
            pv["barrierType"] = p->getBarrierType();
            pv["isBackMove"] = p->getIsBackMove();
            MapPoint * startPoint = static_cast<MapPoint *>(onemap->getSpiritById(p->getStart()));
            MapPoint * endPoint = static_cast<MapPoint *>(onemap->getSpiritById(p->getEnd()));
            if(startPoint && endPoint)
            {
//                pv["length"] = std::sqrt((startPoint->getRealX()- endPoint->getRealX())*
//                                         (startPoint->getRealX()- endPoint->getRealX())
//                                         +(startPoint->getRealY()- endPoint->getRealY())*
//                                         (startPoint->getRealY()- endPoint->getRealY()));
                 pv["length"] = p->getLength();
                pv["locked"] = p->getLocked();
                v_paths.append(pv);
            }
        }
        else if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Background) {
            MapBackground *p = static_cast<MapBackground *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();
//            int lenlen = Base64encode_len(p->getImgDataLen());
//            char *ss = new char[lenlen];
//            Base64encode(ss, p->getImgData(), p->getImgDataLen());
//            pv["data"] = std::string(ss, lenlen);
//            delete ss;
//            pv["data_len"] = p->getImgDataLen();
//            pv["width"] = p->getWidth();
//            pv["height"] = p->getHeight();
            pv["x"] = p->getX();
            pv["y"] = p->getY();
            pv["filename"] = p->getFileName();
            v_bkgs.append(pv);
        }
        else if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Floor) {
            MapFloor *p = static_cast<MapFloor *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();
            pv["bkg"] = p->getBkg();
            pv["originX"] = p->getOriginX();
            pv["originY"] = p->getOriginY();
            pv["rate"] = p->getRate();

            Json::Value ppv;
            auto points = p->getPoints();
            int kk = 0;
            for (auto p : points) {
                ppv[kk++] = p;
            }
            if(!ppv.isNull()>0)
                pv["points"] = ppv;

            Json::Value ppv2;
            auto paths = p->getPaths();
            int kk2 = 0;
            for (auto p : paths) {
                ppv2[kk2++] = p;
            }
            if(!ppv2.isNull()>0)
                pv["paths"] = ppv2;

            v_floors.append(pv);
        }
        else if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Block) {
            MapBlock *p = static_cast<MapBlock *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();

            Json::Value ppv;
            auto ps = p->getSpirits();
            int kk = 0;
            for (auto p : ps) {
                ppv[kk++] = p;
            }
            if(!ppv.isNull()>0)
                pv["spirits"] = ppv;

            v_blocks.append(pv);
        }
        else if (spirit->getSpiritType() == MapSpirit::Map_Sprite_Type_Group) {
            MapGroup *p = static_cast<MapGroup *>(spirit);
            Json::Value pv;
            pv["id"] = p->getId();
            pv["name"] = p->getName();
            pv["type"] = p->getGroupType();
            Json::Value ppv;
            auto ps = p->getSpirits();
            int kk = 0;
            for (auto p : ps) {
                ppv[kk++] = p;
            }
            if(!ppv.isNull()>0)
                pv["spirits"] = ppv;
            v_groups.append(pv);
        }
    }

    if (v_points.size() > 0)
        request["points"] = v_points;
    if (v_paths.size() > 0)
        request["paths"] = v_paths;
    if (v_floors.size() > 0)
        request["floors"] = v_floors;
    if (v_bkgs.size() > 0)
        request["bkgs"] = v_bkgs;
    if (v_blocks.size() > 0)
        request["blocks"] = v_blocks;
    if (v_groups.size() > 0)
        request["groups"] = v_groups;
    request["maxId"] = onemap->getMaxId();
    request["version"] = onemap->getVersion();
    request["displayRatio"] = onemap->getDisplayRatio();

    Json::StyledWriter styled_writer;
    mapInfoOut=styled_writer.write(request);
    return 1;

}
